package cn.javaex.hgo.config.exception;

import java.io.IOException;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import com.google.gson.Gson;

import cn.javaex.hgo.config.constant.HgoErrorMsg;

/**
 * 全局异常处理器
 * 
 * @author 陈霓清
 */
public class HgoExceptionResolver implements HandlerExceptionResolver {

	public ModelAndView resolveException(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception e) {
	
		// 1.0 向控制台打印错误信息
		e.printStackTrace();
		
		// 2.0 定义错误信息
		String message = HgoErrorMsg.ERROR_999999;
		// 2.1 判断异常类型
		if (e instanceof UnauthorizedException) {
			// shiro的权限不足异常
			message = HgoErrorMsg.ERROR_403;
		} else if (e instanceof HgoException) {
			// 自己抛出的异常
			message = ((HgoException)e).getMessage();
		} else if (e instanceof UndeclaredThrowableException) {
			// aop拦截中抛出的异常
			message = ((UndeclaredThrowableException)e).getUndeclaredThrowable().getMessage();
		}
		
		// 3.0 判断是json请求还是页面转发请求
		HandlerMethod handMethod = (HandlerMethod)handler;
		ResponseBody responseBody = handMethod.getMethod().getAnnotation(ResponseBody.class);
		if (responseBody!=null) {
			// json请求（返回json数据）
			Map<String, Object> responseMap = new HashMap<String, Object>();
			responseMap.put("code", "999999");
			responseMap.put("message", message);
			String json = new Gson().toJson(responseMap);
			response.setCharacterEncoding("UTF-8");
			response.setContentType("application/json; charset=utf-8");
			try {
				response.getWriter().write(json);
				response.getWriter().flush();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			
			// 返回一个空的ModelAndView表示已经手动生成响应
			return new ModelAndView();
		}
		
		// 4.0 页面转发（跳转至错误页面）
		ModelAndView modelAndView = new ModelAndView();
		// 4.1 将错误信息传到页面
		modelAndView.addObject("message", message);
		// 4.2 指向错误页面或没有权限页面
		if ((e instanceof UnauthorizedException) || message.equals(HgoErrorMsg.ERROR_403)) {
			// 没有权限异常
			modelAndView.setViewName("error/unauthorize");
		} else {
			modelAndView.setViewName("error/error");
		}
		
		return modelAndView;
	}
}
